﻿using HBKY.Shop.Common;
using HBKY.Shop.Common.LogHelper;
using HBKY.Shop.Common.Redis;
using Quartz;
using System;
using System.Diagnostics;
using System.Threading.Tasks;

namespace HBKY.Shop.Tasks
{
    /// <summary>
    /// job基类
    /// </summary>
    public abstract class JobBase:IJob
    {
        internal readonly IRedisBasketRepository _redisBasketRepository;
        public JobBase(IRedisBasketRepository redisBasketRepository)
        {
            _redisBasketRepository = redisBasketRepository;
        }

        public async Task<string> ExecuteJob(IJobExecutionContext context, Func<Task> func)
        {
            string jobKey = $"ExecuteJob:{context.JobDetail.Key.Group}:{context.JobDetail.Key.Name}";
            string jobHistory = $"【{DateTime.Now}】执行任务【Id：{context.JobDetail.Key.Name}，组别：{context.JobDetail.Key.Group}】";
            var token = Guid.NewGuid().ToString("N"); //锁持有者
            try
            {
                var coon = await _redisBasketRepository.LockTakeAsync(jobKey, token, TimeSpan.FromSeconds(50));
               // if (!coon) return "已经存在任务正在执行!";
                //记录Job时间
                Stopwatch stopwatch = new Stopwatch();
                stopwatch.Start();
                await func();//执行任务
                stopwatch.Stop();
                jobHistory += $"，【执行成功】，完成时间：{stopwatch.Elapsed.TotalMilliseconds.ToString("00")}毫秒";
            }
            catch (Exception ex)
            {
                JobExecutionException e2 = new JobExecutionException(ex);
                //true  是立即重新执行任务 
                e2.RefireImmediately = true;
                jobHistory += $"，【执行失败】，异常日志：{ex.Message}";
                LogManagerNlog.LogError(ex, jobHistory);
            }
            finally 
            {
                //释放锁
                _redisBasketRepository.LockRelease(jobKey, token);
            }
            LogManagerNlog.LogInformation(jobHistory);
            return jobHistory;
        }

        public async Task Execute(IJobExecutionContext context)
        {
            var jobKey = context.JobDetail.Key;
            var jobId = jobKey.Name;
            var executeLog = await ExecuteJob(context, async () => await Run(context, jobId.ObjToInt()));
        }

        public abstract Task Run(IJobExecutionContext context, int jobid);

    }
}
